package com.saikuo.service.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.saikuo.service.api.ApiResultModel;
import com.saikuo.service.api.ErrorCode;
import com.saikuo.service.constant.*;
import com.saikuo.service.dao.IMedicineDao;
import com.saikuo.service.dao.IOrderDao;
import com.saikuo.service.jpush.PushManage;
import com.saikuo.service.model.Order;
import com.saikuo.service.service.IPayService;
import com.saikuo.service.utils.DateUtils;
import com.saikuo.service.utils.HttpClientUtils;
import com.saikuo.service.utils.StringUtil;
import com.saikuo.service.utils.WinXinUtils;
import com.saikuo.service.vo.MedicineView;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xml.sax.InputSource;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by shanchangyu on 16/10/18.
 */
@Service
public class PayServiceImpl implements IPayService {
    private static final Logger logger = LoggerFactory.getLogger("pay");
    @Autowired
    private SalipayConfig salipayConfig;
    @Autowired
    private LalipayConfig lalipayConfig;
    @Autowired
    private WeiXinConfig wechatConfig;
    @Autowired
    private JpushConfig jpushConfig;
    @Autowired
    private IOrderDao orderDao;

    @Autowired
    private IMedicineDao medicineDao;

    @Override
    public ApiResultModel payOrder(Long orderId, int payType, HttpServletRequest request) {
        Order order = orderDao.getOrderByOrderId(orderId);
        if (order == null) {
            return new ApiResultModel(ErrorCode.ORDER_NOT_EXIST);
        }
        if (payType == PayType.WECHAT.getValue()) {//微信
            return weChatPay(order, request);
        } else if (payType == PayType.ALIPAY.getValue()) {//支付宝
            return aliPay(order);
        }
        return new ApiResultModel();
    }

    private ApiResultModel aliPay(Order order) {
        String appId = salipayConfig.getsAliPayAppId();
        String privateKey = salipayConfig.getsAliPayPrivateKey();
        String notifyUrl = salipayConfig.getsAliNotifyUrl();
        if (order.getDeliveryWay() == DeliveryType.DOOR.getValue()) {
            appId = lalipayConfig.getlAliPayAppId();
            privateKey = lalipayConfig.getlAliPayPrivateKey();
            notifyUrl = lalipayConfig.getlAliNotifyUrl();
        }
        Map<String, String> map = new HashMap<>();
        map.put("app_id", appId);// 商户appid
        map.put("method", AlipayConstants.ALIPAY_MATCHOD);// 接口名
        map.put("charset", AlipayConstants.CHARSET);
        map.put("format", AlipayConstants.FORMAT);
        map.put("sign_type", AlipayConstants.SIGN_TYPE);
        map.put("timestamp", DateUtils.getDateOfYMDHMSString(new Date()));
        map.put("version", AlipayConstants.VERSION);
        map.put("notify_url", notifyUrl);
        map.put("biz_content", bizContent(order));
        try {
            String signContent = AlipaySignature.getSignContent(map);
            String orderString = AlipaySignature.rsaSign(signContent, privateKey, AlipayConstants.CHARSET);
            String backParam = StringUtil.getEncodeContent(map, AlipayConstants.CHARSET) + "&sign=" + URLEncoder.encode(orderString, AlipayConstants.CHARSET);
            System.out.println("aliPay 签名返回=====" + backParam);
            Map<String, String> backMap = new HashMap<>();
            backMap.put("orderString", backParam);
            return new ApiResultModel(backMap);
        } catch (AlipayApiException e) {
            logger.info("AlipayApiException error======", e);
        } catch (UnsupportedEncodingException e) {
            logger.info("UnsupportedEncodingException error======", e);
        }
        return new ApiResultModel();
    }

    private String bizContent(Order order) {
        StringBuilder sb = new StringBuilder();
        sb.append("{" +
                "\"out_trade_no\":\"" + order.getOrderId().toString() + "\"," +
                 "\"total_amount\":\"" + order.getPrice().toString() + "\"," +
                //"\"total_amount\":\"0.01\"," +
                "\"subject\":\"药到app商品\"," +
                "\"product_code\":\"QUICK_MSECURITY_PAY\"" +
                "}");
        return sb.toString();
    }

    private ApiResultModel weChatPay(Order order, HttpServletRequest request) {
        ApiResultModel apiResultModel = new ApiResultModel();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        Date now = new Date();
        Map<String, Object> map = new HashMap<>();
        map.put("nonce_str", WinXinUtils.buildRandom());// 随机字符串
        map.put("appid", wechatConfig.getWeChatAppId());// 商户appid
        map.put("out_trade_no", order.getOrderId().toString());// 商户订单
        map.put("mch_id", wechatConfig.getWeChatMchId());// 商户号
        map.put("device_info", "WEB");// 终端设备号(门店号或收银设备ID)，默认请传"WEB"
        map.put("body", "药到app商品");// 商品描述
        map.put("detail", "商品详情");// 商品详情
        map.put("attach", "赛阔科技");// 附加数据
        map.put("fee_type", "CNY");// 货币类型
        map.put("total_fee", StringUtil.doubleToInt(order.getPrice()*100));
        //map.put("total_fee", 1);// 总金额
        map.put("spbill_create_ip", HttpClientUtils.getIpAddr(request));// 终端IP:用户端实际ip
        map.put("time_start", format.format(now));// 交易起始时间
        map.put("time_expire", format.format(now.getTime() + 300000));// 交易结束时间(限制五分钟)
        map.put("goods_tag", "WXG");// 商品标记
        map.put("notify_url",
                wechatConfig.getWeChatNotifyUrl());// 接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
        map.put("trade_type", "APP");// 支付类型
        map.put("limit_pay", "no_credit");// 指定支付方式:no_credit--指定不能使用信用卡支付
        map.put("sign", WinXinUtils.createSign(map, wechatConfig.getWeChatKey()));// 签名
        String xml = "";
        try {
            xml = WinXinUtils.unifiedorder(wechatConfig.getWeChatUrl(), WinXinUtils.createPayXML(map));
            System.out.println("========发送返回：" + xml);
        } catch (Exception e) {
            logger.info("weChatPay error======", e);
        }
        logger.info("weChatPay  result======" + xml);
        Element el = WinXinUtils.xmlToElement(xml);
        if (el != null && "SUCCESS".equals(el.getChildText("return_code"))) {
            // 微信端返回值再次签名
            Map<String, Object> remap = new HashMap<>();
            String str = WinXinUtils.buildRandom();
            String temp = String.valueOf(System.currentTimeMillis() / 1000);
            remap.put("appid", wechatConfig.getWeChatAppId());
            remap.put("partnerid", wechatConfig.getWeChatPartnerId());
            remap.put("package", "Sign=WXPay");
            remap.put("noncestr", str);
            remap.put("timestamp", temp);
            remap.put("prepayid", el.getChildText("prepay_id"));
            // 返回给手机客户端
            Map<String, Object> result = new HashMap<>();
            result.put("sign", WinXinUtils.createSign(remap, wechatConfig.getWeChatKey()));
            result.put("orderId", order.getOrderId().toString());
            result.put("appid", wechatConfig.getWeChatAppId());
            result.put("partnerid", wechatConfig.getWeChatPartnerId());
            result.put("packagesign", "Sign=WXPay");
            result.put("noncestr", str);
            result.put("timestamp", temp);
            result.put("prepayid", el.getChildText("prepay_id"));
            apiResultModel.setData(result);
        }
        return apiResultModel;
    }

    @Override
    public void weChatNotifyUrl(ServletRequest request, ServletResponse response) throws IOException, JDOMException {
        // 获取微信POST过来反馈信息xml
        StringBuilder sbxml = new StringBuilder();
        InputStream is = request.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is,
                "UTF-8"));
        String buffer = null;
        while ((buffer = br.readLine()) != null) {
            sbxml.append(buffer);
        }
        logger.info("weChatPay notify======" + sbxml.toString());
        // 对xml进行解析
        if (sbxml.toString() != null && sbxml.toString().length() != 0) {
            StringReader read = new StringReader(sbxml.toString());
            InputSource source = new InputSource(read);
            SAXBuilder sb = new SAXBuilder();
            Document doc = sb.build(source);
            Element element = doc.getRootElement();
            logger.info("weChatPay notify======" + "返回状态码:" + element.getChildText("return_code")
                    + "返回信息:" + element.getChildText("return_msg"));
            if ("SUCCESS".equals(element.getChildText("return_code"))) {
                Long orderId = Long.valueOf(element.getChildText("out_trade_no"));
                orderDao.completeOrderInfo(orderId, OrderStatus.WAIT_DELIVERY.getValue(), PayType.WECHAT.getValue());
                List<MedicineView> list = medicineDao.getMedicineDetailByOrderId(orderId);
                medicineDao.updateMedicineSaleCount(list);//修改医药表销量
                //推送给商户平台
                PushManage pushManage = new PushManage();
                pushManage.sendPushPlatform(jpushConfig.getPlatformAppKey(), jpushConfig.getPlatformMasterSecret(), orderDao.getStoreCodeByOrderId(orderId), orderId);
                // 获取post来的 xml参数 在返给微信时需要回传
                response.getWriter().write("success");
            } else {
                response.getWriter().write("fail");
            }
            response.getWriter().flush();
            response.getWriter().close();
        }
    }

    @Override
    public void aliPayNotifyUrl(ServletRequest request, ServletResponse response, int deliveryWay) throws IOException {
        String appId = salipayConfig.getsAliPayAppId();
        String aliPayPublicKey = salipayConfig.getsAliPayPublicKey();
        if (deliveryWay == DeliveryType.DOOR.getValue()) {
            appId = lalipayConfig.getlAliPayAppId();
            aliPayPublicKey = lalipayConfig.getlAliPayPublicKey();
        }
        boolean backFlag = false;
        Map<String, String> paramsMap = HttpClientUtils.getRequestParams(request);
        logger.info("aliPay notify======" + paramsMap);
        try {
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, aliPayPublicKey, AlipayConstants.CHARSET); //调用SDK验证签名
            System.out.println("aliPay signVerified======" + signVerified + "====appId===" + appId + "===paramsMap.get(\"app_id\")===" + paramsMap.get("app_id"));
            if (signVerified && paramsMap.get("app_id").equals(appId)) {
                Order order = orderDao.getOrderByOrderId(Long.valueOf(paramsMap.get("out_trade_no")));
                if (order != null && order.getPrice().equals(Double.valueOf(paramsMap.get("total_amount")))
                        && "TRADE_SUCCESS".equals(paramsMap.get("trade_status"))) {
                    backFlag = true;
                    //推送给商户平台
                    PushManage pushManage = new PushManage();
                    pushManage.sendPushPlatform(jpushConfig.getPlatformAppKey(), jpushConfig.getPlatformMasterSecret(), order.getStoreCode(), Long.valueOf(paramsMap.get("out_trade_no")));
                }
            }
            if (backFlag) {
                List<MedicineView> list = medicineDao.getMedicineDetailByOrderId(Long.valueOf(paramsMap.get("out_trade_no")));
                medicineDao.updateMedicineSaleCount(list);//修改医药表销量
                orderDao.completeOrderInfo(Long.valueOf(paramsMap.get("out_trade_no")), OrderStatus.WAIT_DELIVERY.getValue(), PayType.ALIPAY.getValue());
                response.getWriter().write("success");
            } else {
                response.getWriter().write("fail");
            }
            response.getWriter().flush();
            response.getWriter().close();
        } catch (AlipayApiException e) {
            logger.info("aliPay notify_error======", e);
        }
    }


}
